/**
 * 2025/01/01 - 2025/12/31
 */
package com.snail.starter.utils.tree;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zgadmin
 * @date 2025/9/26 19:30
 */
public class TreeUtil {

    /**
     * 平铺转父子结构
     * @param tList 平铺数据
     * @param tpkFunction 父子关系标识
     * @param trFunction 单个对象转换
     * @param tkFunction 子的标识
     * @param childConsumer 所有的子数据
     * @param orderByFunction 排序
     * @return 父子结构
     * @param <T> 转换前的类
     * @param <K> 对象唯一标识
     * @param <R> 转换后的类
     * @param <O> 排序
     */
    public static <T, K, R, O extends Comparable<? super O>> List<R> buildTree(List<T> tList, Function<T, K> tpkFunction,
                                                                               Function<T, R> trFunction, Function<T, K> tkFunction,
                                                                               BiConsumer<R, List<R>> childConsumer, Function<R, O> orderByFunction) {
        if (null == tList || tList.isEmpty()) {
            return new ArrayList<>();
        }
        return buildTree(tList, tList.stream().collect(Collectors.groupingBy(tpkFunction)), trFunction, tkFunction, childConsumer, orderByFunction);
    }

    public static <T, U, R> List<R> buildList(U pId, List<T> treeList, Function<T, U> idFunction, BiFunction<T, U, R> trFunction,
                                              Function<T, Stream<T>> childrenFunction) {
        return treeList
                .stream()
                .flatMap(t -> TreeUtil.build(pId, t, idFunction, trFunction, childrenFunction))
                .collect(Collectors.toList());
    }

    public static <T, U, R> Stream<R> build(U pId, T t, Function<T, U> idFunction, BiFunction<T, U, R> trFunction, Function<T, Stream<T>> childrenFunction) {
        if (null == t) {
            return Stream.empty();
        }
        Stream<R> childrenStream = childrenFunction.apply(t).flatMap(child -> TreeUtil.build(idFunction.apply(t), child, idFunction, trFunction, childrenFunction));
        return Stream.concat(Stream.of(trFunction.apply(t, pId)), childrenStream);
    }

    /**
     * 平铺转父子结构
     * @param tList 平铺数据
     * @param tMap 父子一对多映射
     * @param trFunction 单个对象转换
     * @param tkFunction 子的标识
     * @param childConsumer 所有的子数据
     * @param orderByFunction 排序
     * @return 父子结构
     * @param <T> 转换前的类
     * @param <K> 对象唯一标识
     * @param <R> 转换后的类
     * @param <O> 排序
     */
    private static <T, K, R, O extends Comparable<? super O>> List<R> buildTree(List<T> tList, Map<K, List<T>> tMap,
                                                                                Function<T, R> trFunction, Function<T, K> tkFunction,
                                                                                BiConsumer<R, List<R>> childConsumer, Function<R, O> orderByFunction) {
        if (null == tList || tList.isEmpty()) {
            return new ArrayList<>();
        }
        return tList.stream()
                .filter(t -> tMap.containsKey(tkFunction.apply(t)) && !tMap.get(tkFunction.apply(t)).isEmpty())
                .map(t -> {
                    R r = trFunction.apply(t);
                    childConsumer.accept(r,
                            buildTree(tMap.get(tkFunction.apply(t)), tMap, trFunction, tkFunction, childConsumer, orderByFunction)
                                    .stream().sorted(Comparator.comparing(orderByFunction)).collect(Collectors.toList()));
                    return r;
                }).sorted(Comparator.comparing(orderByFunction)).collect(Collectors.toList());
    }
}
